package vip.wangwenhao.sso.config.security.filter;

import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import vip.wangwenhao.autoconfigure.utils.Oauth2Utils;
import vip.wangwenhao.common.enums.ResultCode;
import vip.wangwenhao.common.exception.CommonException;
import vip.wangwenhao.common.result.Result;
import vip.wangwenhao.common.util.HttpUtils;
import vip.wangwenhao.sso.constants.Oauth2Constants;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class ClientDetailsAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private ClientDetailsService clientDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 只有获取token的时候需要携带携带客户端信息，放过其他
        if (!Oauth2Constants.AUTH_CLIENT_URL.stream().anyMatch(s -> s.equals(request.getRequestURI()))) {
            filterChain.doFilter(request, response);
            return;
        }

        String[] clientDetails;
        try {
            clientDetails = Oauth2Utils.isHasClientDetails(request);
        } catch (Exception e) {
            HttpUtils.response(response, HttpStatus.SC_OK, Result.fail(ResultCode.AUTHORIZATION_INVALID, e.getMessage()));
            return;
        }

        this.handle(request, response, clientDetails, filterChain);
    }

    private void handle(HttpServletRequest request, HttpServletResponse response, String[] clientDetails, FilterChain filterChain) throws IOException, ServletException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

        if (authentication != null && authentication.isAuthenticated()) {
            filterChain.doFilter(request, response);
            return;
        }
        try {
            ClientDetails clientDetail = this.clientDetailsService.loadClientByClientId(clientDetails[0]);
            if (!passwordEncoder.matches(clientDetails[1],clientDetail.getClientSecret())){
                throw new CommonException("client secret is error");
            }
        } catch (Exception e) {
            HttpUtils.response(response, HttpStatus.SC_OK, Result.fail(ResultCode.AUTHORIZATION_INVALID, e.getMessage()));
            return;
        }

        filterChain.doFilter(request, response);
    }
}